/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.util.ArrayList;
import java.util.Collections;

class GlobalConfig {
    public static final int BASE_VALUE = 1000;
    public static final int LOOP_I_MAX_600000 = 600000;
    public static final int LOOP_MAX_4 = 4;
    public static final int NUMBER_31 = 31;
    public static final int NUMBER_32 = 32;
    public static final int NUMBER_1000 = 1000;
    public static final int NUMBER_N100000 = 100000;
    public static final int NUMBER_2147483647 = 2147483647;
    public static final int NUMBER_N2147483648 = -2147483648;
    public static final int BIT_BINARY_NUMBER_5 = 5;
    public static final int BIT_BINARY_NUMBER_10000 = 10000;
    public static final int EXECUTION_MAX_80 = 80;

    public static boolean inDebug = false;
    public static void log(String str) {
        if (inDebug) {
            System.out.println(str);
        }
    }
    public static double currentTimestamp13() {
        return (double) System.nanoTime() / 1_000_000;
    }

    public static String pad(int number, int width) {
        String s = String.valueOf(number);
        int prefixWidth = width - s.length();
        if (prefixWidth > 0) {
            for (int i = 0; i < prefixWidth; i++) {
                s = ' ' + s;
            }
        }
        return s;
    }

    public static void primes(ArrayList<Integer> isPrime, int n) {
        int count = 0;
        int m = BIT_BINARY_NUMBER_10000 << n;
        int size = (m + NUMBER_31) >> BIT_BINARY_NUMBER_5;
        for (int i = 0; i < size; i++) {
            isPrime.set(i, 0xffffffff);
        }
        for (int i = 2; i < m; i++) {
            if ((isPrime.get(i >> BIT_BINARY_NUMBER_5) & (1 << i % NUMBER_32)) != 0) {
                int j = i + i;
                while (j < m) {
                    int tmp = Config.transBigInt32(isPrime.get(j >> BIT_BINARY_NUMBER_5));
                    tmp &= Config.transBigInt32(~(1 << (j & NUMBER_31)));
                    isPrime.set(j >> BIT_BINARY_NUMBER_5, tmp);
                    j += i;
                }
                count += 1;
            }
        }
    }

    public static ArrayList<Integer> sieve() {
        ArrayList<Integer> isPrime = new ArrayList<Integer>();
        for (int i = LOOP_MAX_4; i <= LOOP_MAX_4; i++) {
            isPrime = new ArrayList<Integer>(Collections.nCopies(((BIT_BINARY_NUMBER_10000 << i) + NUMBER_31) >> BIT_BINARY_NUMBER_5, null));
            primes(isPrime, i);
        }

        return isPrime;
    }
}
/*
 * @State
 * @Tags Jetstream2
 */
class Benchmark {
    /*
     * @Benchmark
     */
    public void run() {
        ArrayList<Integer> result = GlobalConfig.sieve();
        Long sum = 0L;
        for (int i = 0; i < result.size(); i++) {
            sum += result.get(i);
            if (GlobalConfig.inDebug && i % GlobalConfig.NUMBER_1000 == 0) {
                GlobalConfig.log(String.format("bitops-nsieve-bits: i = %d sum= %d", i, sum));
            }
        }

        long expected = -1286749544853L;
        if (sum != expected) {
            throw new Error("ERROR: bad result: expected " + expected + " but got " + sum);
        }
    }

    public static void main(String[] args) {
        double startTime = GlobalConfig.currentTimestamp13();
        Benchmark benchmark = new Benchmark();
        for (int i = 0; i < GlobalConfig.EXECUTION_MAX_80; i++) {
            double startTimeInLoop = GlobalConfig.currentTimestamp13();
            benchmark.run();
            double endTimeInLoop = GlobalConfig.currentTimestamp13();
//            GlobalConfig.log(String.format( "bitops-nsieve-bits: ms = %d i = %d", endTimeInLoop - startTimeInLoop, i));
        }
        double endTime = GlobalConfig.currentTimestamp13();
        System.out.println("bitops-nsieve-bits: ms = " + (endTime - startTime));
    }
}
class Config {
    public static int transBigInt32(long bigInt32Num) {
        long tmp = bigInt32Num;
        if (tmp > GlobalConfig.NUMBER_2147483647) {
            long max = 4294967295L;
            tmp = tmp % (max + 1);
            if (tmp > GlobalConfig.NUMBER_2147483647) {
                tmp = tmp - max - 1;
            }
        } else if (tmp < GlobalConfig.NUMBER_N2147483648) {
            long max = 4294967295L;
            tmp = tmp % (max + 1);
            if (tmp < GlobalConfig.NUMBER_N2147483648) {
                tmp = tmp + max + 1;
            }
        }
        return (int) tmp;
    }
}